package com.gzhryc.html;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;

import com.gzhryc.common.json.JsonTools;
import com.gzhryc.html.dao.db.Website;
import com.gzhryc.html.dao.db.WebsitePage;
import com.gzhryc.html.dao.enums.WebsiteEnum;
import com.gzhryc.html.models.PageBanners;
import com.gzhryc.html.models.PageData;
import com.gzhryc.html.models.WebsiteData;
import com.gzhryc.servlet.VelocityService;

import eu.bitwalker.useragentutils.DeviceType;
import eu.bitwalker.useragentutils.UserAgent;

public class ViewHelper {
	
	static ConcurrentHashMap<Long,WebsiteData> WebsiteCache = new ConcurrentHashMap<Long,WebsiteData>();
	
	static Website website;
	
	public static void initial() {
		WebsiteService websiteService = new WebsiteService();
		WebsitePageService websitePageService = new WebsitePageService();
		List<Website> websiteList = websiteService.findByStatus(WebsiteEnum.State.Usable.index());
		if(websiteList != null) {
			for(Website website : websiteList) {
				List<WebsitePage> pages = websitePageService.findByWebsiteId(website.getId());
				WebsiteData data = new WebsiteData(website);
				data.setPages(pages);
				WebsiteCache.put(website.getId(),data);
			}
		}
	}
	
	public static void refresh() {
		WebsiteService websiteService = new WebsiteService();
		WebsitePageService websitePageService = new WebsitePageService();
		List<Website> websiteList = websiteService.findByStatus(WebsiteEnum.State.Usable.index());
		if(websiteList != null) {
			List<Long> idList = new ArrayList<Long>();
			for(Website website : websiteList) {
				idList.add(website.getId());
				List<WebsitePage> pages = websitePageService.findByWebsiteId(website.getId());
				WebsiteData data = WebsiteCache.get(website.getId());
				if(data != null && data.getWebsite().getUpdateDate() != null) {
					if(data.getWebsite().getUpdateDate().getTime() != website.getUpdateDate().getTime()) {
						data.setWebsite(website);
					}
					//更新页面配置
					List<String> pathList = new ArrayList<String>();
					for(WebsitePage page : pages) {
						pathList.add(page.getPath());
						WebsitePage item = data.getPage(page.getPath());
						if(item != null) {
							if(item.getUpdateDate().getTime() != page.getUpdateDate().getTime()) {
								data.setPage(item);
							}
						}else {
							data.setPage(page);
						}
					}
					data.removeNotContains(pathList);
				}else {
					data = new WebsiteData(website);
					data.setPages(pages);
					WebsiteCache.put(website.getId(),data);
				}
			}
			removeNotContains(idList);
		}
	}
	
	public static void setWebsite(String htmlTheme) {
		website = new Website();
		website.setId(0L);
		website.setPathPrefix("/");
		website.setHtmlTheme(htmlTheme);
		website.setType(WebsiteEnum.Type.Auto.index());
		website.setState(WebsiteEnum.State.Usable.index());
		WebsiteData data = new WebsiteData(website);
		WebsiteCache.put(website.getId(), data);
	}
	
	public static void setWebsite(Website website) {
		WebsiteData data = new WebsiteData(website);
		WebsiteCache.put(website.getId(), data);
	}
	
	public static void removeNotContains(List<Long> idList) {
		Enumeration<Long> enumeration = WebsiteCache.keys();
		List<Long> temp = new ArrayList<Long>();
		while(enumeration.hasMoreElements()) {
			Long key = enumeration.nextElement();
			if(!idList.contains(key)) {
				temp.add(key);
			}
		}
		for(Long key : temp) {
			WebsiteCache.remove(key);
		}
	}

	public static PageData getPage(HttpServletRequest req) {
		String contextPath = req.getContextPath();
		UserAgent userAgent = UserAgent.parseUserAgentString(req.getHeader("User-Agent"));
		String lang = req.getLocale().getLanguage();
		String url = req.getRequestURI();
		if(StringUtils.isNotBlank(contextPath) && !contextPath.equals("/")) {
			url = url.replaceFirst(contextPath, "");
		}
		List<WebsiteDataWrap> tempCache = findWebsiteData(contextPath,userAgent,lang);
		PageData pageData = getConfigPage(tempCache,url);
		if(pageData == null) {
			pageData = getPage(tempCache,url);
		}
		return pageData;
	}
	
	/**
	 * 获取配置的路径
	 * @param tempCache
	 * @param url
	 * @return
	 */
	public static PageData getConfigPage(List<WebsiteDataWrap> tempCache,String url) {
		if(tempCache.size() > 0) {
			WebsiteData websiteData = null;
			WebsitePage page = null;
			for(WebsiteDataWrap wrap : tempCache) {
				page = wrap.getWebsiteData().matchPage(url);
				if(page != null) {
					websiteData = wrap.getWebsiteData();
					//检查模板是否存在
					String templateName = "/"+websiteData.getWebsite().getHtmlTheme() + "/html" + page.getTemplatePath();
					VelocityService velocityService = VelocityService.self();
					if(velocityService.resourceExists(templateName)) {
						break;
					}else {
						page = null;
						websiteData = null;
					}
				}
			}
			
			if(websiteData != null && page != null) {
				PageData pageData = new PageData();
				pageData.setTitle(page.getTitle());
				pageData.setKeywords(page.getKeywords());
				pageData.setDescription(page.getDescription());
				pageData.setHeadHtml(page.getHeadHtml());
				pageData.setFootHtml(page.getFootHtml());
				pageData.setLang(websiteData.getWebsite().getLang());
				if(StringUtils.isNotBlank(page.getBanners())) {
					PageBanners banners = JsonTools.fromJson(page.getBanners(), PageBanners.class);
					pageData.setBanners(banners.getItems());
				}
				pageData.setTemplatePath("/"+websiteData.getWebsite().getHtmlTheme() + "/html" + page.getTemplatePath());
				return pageData;
			}
		}
		
		return null;
	}
	
	public static PageData getPage(List<WebsiteDataWrap> tempCache,String url) {
		if(tempCache.size() > 0) {
			WebsiteData websiteData = null;
			PageData pageData = null;
			for(WebsiteDataWrap wrap : tempCache) {
				websiteData = wrap.getWebsiteData();
				String templateName = "/"+websiteData.getWebsite().getHtmlTheme() + "/html" + url;
				VelocityService velocityService = VelocityService.self();
				if(velocityService.resourceExists(templateName)) {
					pageData = new PageData();
					pageData.setTitle(websiteData.getWebsite().getTitle());
					pageData.setKeywords(websiteData.getWebsite().getKeywords());
					pageData.setDescription(websiteData.getWebsite().getDescription());
					pageData.setHeadHtml(websiteData.getWebsite().getHeadHtml());
					pageData.setFootHtml(websiteData.getWebsite().getFootHtml());
					pageData.setLang(websiteData.getWebsite().getLang());
					pageData.setTemplatePath(templateName);
					break;
				}
			}
			return pageData;
		}
		return null;
	}
	
	public static List<WebsiteDataWrap> findWebsiteData(String contextPath,UserAgent userAgent,String lang){
		DeviceType deviceType = userAgent.getOperatingSystem().getDeviceType();
		boolean isMobile = DeviceType.MOBILE.equals(deviceType) || DeviceType.TABLET.equals(deviceType);
		List<WebsiteDataWrap> tempCache = new ArrayList<WebsiteDataWrap>();
		//TODO 多线程安全控制，因为改动很少则暂不考虑线程安全
		for(WebsiteData data : WebsiteCache.values()) {
			Integer weight = data.matchPathPrefix(contextPath);
			if(weight > 0) {
				weight = weight + data.matchType(isMobile);
				weight = weight + data.matchLang(lang);
				tempCache.add(new WebsiteDataWrap(data,weight));
			}
		}
		if(tempCache.size() > 0) {
			Collections.sort(tempCache);  //按权重排序
		}
		return tempCache;
	}
	
	public static class WebsiteDataWrap implements Comparable<WebsiteDataWrap>{
		
		private final WebsiteData websiteData;
		private final Integer weight;
		
		public WebsiteDataWrap(WebsiteData websiteData,Integer weight) {
			this.websiteData = websiteData;
			this.weight = weight;
		}

		public WebsiteData getWebsiteData() {
			return websiteData;
		}

		public Integer getWeight() {
			return weight;
		}

		@Override
		public int compareTo(WebsiteDataWrap o) {
			//从大到小排序
			return o.getWeight() - this.getWeight();
		}
	}
}
